www.gusucode.com > wxApp PHP版微信小程序CMS系统 v1.0PHP源码程序 > wxApp PHP版微信小程序CMS系统 v1.0/wxAppCMS_v1.0.0/wxAppCMS_v1.0.0/app/apps/apps_store.class.php
<?php /** * iCMS - i Content Management System * Copyright (c) 2007-2017 iCMSdev.com. All rights reserved. * * @author icmsdev <master@icmsdev.com> * @site https://www.icmsdev.com * @licence https://www.icmsdev.com/LICENSE.html */ defined('iPHP') OR exit('What are you doing?'); class apps_store { const STORE_URL = "https://store.icmsdev.com/v2"; public static $zip_name = null; public static $zip_file = null; public static $is_git = false; public static $is_update = false; public static $test = false; public static $success = false; public static $msg_mode = null; public static $app_id = null; public static $uptime = 0; public static $authcode = null; public static function download($url=null,$name,$zip_name=null) { self::$success = false; strpos($url, '/git/')!==false && self::$is_git = true; $cache_dir = iPATH . 'cache/iCMS/store/'; iFS::mkdir($cache_dir); if(empty($zip_name)){ $zip_name = basename($url); $zip_name = strstr($zip_name, '?', true); } self::$zip_file = $cache_dir . $zip_name; //临时文件 $msg = self::msg('正在下载 [' . $name . '] 安装包',true); if (iFS::ex(self::$zip_file) && (filemtime(self::$zip_file)-time()<3600)) { $msg.= self::msg('安装包已存在',true); self::$success = true; return $msg; } $data = self::remote($url); if($data[0] == '{'){ $array = json_decode($data,true); if($array){ $msg.= self::msg($array['msg'],false); }else{ $msg.= self::msg('下载出错误',false); } }else if ($data) { iFS::write(self::$zip_file, $data); //下载更新包 $msg.= self::msg('安装包下载完成',true); self::$success = true; }else{ $msg.= self::msg('下载出错误',false); } return $msg; } public static function install_template($dir=null) { self::$success = false; $archive_files = self::setup_zip(); $msg = null; if ($archive_files) { $setup_msg = self::setup_template_file($archive_files,$dir); if(is_array($setup_msg)){ $msg.= $setup_msg[0]; }else{ return self::msg($msg.$setup_msg); } } self::$test OR iFS::rm(self::$zip_file); $msg.= self::msg('模板安装完成',true); self::$success = true; return $msg; } public static function install_app($app=null) { self::$success = false; $archive_files = self::setup_zip(); $msg = null; //安装应用数据 $setup_msg = self::setup_app_data($archive_files,$app); if($setup_msg===true){ $msg.= self::msg('应用数据安装完成',true); }else{ if($setup_msg===false){ }else{ if(!self::$is_update){ return self::msg($setup_msg.'安装出错',false); } } } //创建应用表 if(self::setup_app_table($archive_files,$app)){ $msg.= self::msg('应用表创建完成',true); } if (count($archive_files)>0) { $setup_msg = self::setup_app_file($archive_files,$app); if(is_array($setup_msg)){ $msg.= $setup_msg[0]; }else{ return self::msg($msg.$setup_msg); } } self::$test OR iFS::rm(self::$zip_file); if(self::$is_update){ $msg.= self::setup_update($app); }else{ $msg.= self::setup_install($app); } apps::cache() && $msg.= self::msg('更新应用缓存',true); menu::cache() && $msg.= self::msg('更新菜单缓存',true); $msg.= self::msg('应用安装完成',true); self::$success = true; return $msg; } public static function setup_template_file(&$archive_files,$dir){ $msg = self::msg('正在对安装包进行解压缩',true); $msg.= self::msg('解压完成',true); $msg.= self::msg('开始测试目录权限',true); if (!iFS::checkDir(iPATH)) { return self::msg(iPATH.'根目录无写权限',false); } if (!iFS::checkDir(iPHP_TPL_DIR)) { return self::msg(iPHP_TPL_DIR . '目录无写权限',false); } $ROOTPATH = self::rootpath('TPL'); self::$is_git OR $ROOTPATH.= '/'.$dir; $continue = self::extract_test($archive_files,$ROOTPATH,$msg); if (!$continue) { $msg.= self::msg('权限测试无法完成',false); $msg.= self::msg('请设置好上面提示的文件写权限',false); $msg.= self::msg('然后重新安装',false); return $msg; } $msg.= self::msg('权限测试通过',true); self::$test OR iFS::mkdir($ROOTPATH); $bakdir = self::create_bakdir($dir,$msg); $msg.= self::msg('开始安装模板',true); $msg.= self::extract($archive_files,$ROOTPATH,$bakdir); return array($msg,true); } public static function setup_app_data(&$archive_files,$app){ foreach ($archive_files AS $key => $file) { $filename = basename($file['filename']); if($filename=="iCMS.APP.DATA.php"){ unset($archive_files[$key]); $content = get_php_content($file['content']); $content = base64_decode($content); $array = unserialize($content); $check_app = iDB::value(" SELECT `id` FROM `#iCMS@__apps` WHERE `app` ='".$array['app']."' "); if($check_app){ $_msg = self::msg('检测应用是否存在',false); return self::msg($_msg.'该应用已经存在',false); } if($array['table']){ $tableArray = apps::table_item($array['table']); foreach ($tableArray AS $value) { if(iDB::check_table($value['table'],false)){ $_msg = self::msg('检测应用表是否存在',false); return self::msg($_msg.'['.$value['table'].']数据表已经存在'); } } } $array['addtime'] = time(); $array = array_map('addslashes', $array); self::$test OR self::$app_id = iDB::insert("apps",$array); return true; } } return false; } public static function setup_app_table(&$archive_files){ foreach ($archive_files AS $key => $file) { $filename = basename($file['filename']); if($filename=="iCMS.APP.TABLE.php"){ unset($archive_files[$key]); $content = get_php_content($file['content']); if(strpos($content, 'IF NOT EXISTS')===false){ $content = str_replace('CREATE TABLE `', 'CREATE TABLE IF NOT EXISTS `', $content); $content = str_replace('create table `', 'CREATE TABLE IF NOT EXISTS `', $content); } if(!self::$test){ $content && apps_db::multi_query($content); } return true; } } return false; } public static function setup_app_file(&$archive_files,$app){ $msg = self::msg('正在对安装包进行解压缩',true); $msg.= self::msg('解压完成',true); $msg.= self::msg('开始测试目录权限',true); if (!iFS::checkDir(iPATH)) { return self::msg(iPATH.'根目录无写权限',false); } if (!iFS::checkDir(iPHP_APP_DIR)) { return self::msg(iPHP_APP_DIR . '目录无写权限',false); } if (!iFS::checkDir(iPHP_TPL_DIR)) { return self::msg(iPHP_TPL_DIR . '模板无写权限',false); } $ROOTPATH = self::rootpath(); //测试目录文件是否写 $continue = self::extract_test($archive_files,$ROOTPATH,$msg); if (!$continue) { $msg.= self::msg('权限测试无法完成',false); $msg.= self::msg('请设置好上面提示的文件写权限',false); $msg.= self::msg('然后重新安装',false); return $msg; } $msg.= self::msg('权限测试通过',true); $bakdir = self::create_bakdir($app,$msg); $msg.= self::msg('开始安装应用',true); $msg.= self::extract($archive_files,$ROOTPATH,$bakdir); return array($msg,true); } public static function setup_update($app){ $ROOTPATH = iPHP_APP_DIR.'/'.$app.'/'; foreach (glob($ROOTPATH."iCMS.APP.UPDATE.*.php") as $filename) { $d = str_replace(array($ROOTPATH,'iCMS.APP.UPDATE.','.php'), '', $filename); $time = strtotime($d.'00'); if($time>self::$uptime){ $files[$d] = $filename; } } if($files){ ksort($files); foreach ($files as $key => $file) { $name = $app.'_'.str_replace(array('.php','.'), array('','_'), basename($file)); $msg.= self::setup_exec($file,$name,'升级'); } } return $msg; } public static function setup_zip() { $zip_file = self::$zip_file; if(!file_exists($zip_file)){ return self::msg("安装包不存在",false); } iPHP::vendor('PclZip'); $zip = new PclZip($zip_file); if (false == ($archive_files = $zip->extract(PCLZIP_OPT_EXTRACT_AS_STRING))) { iFS::rm($zip_file); return self::msg("ZIP包错误",false); } if (0 == count($archive_files)) { iFS::rm($zip_file); return self::msg("空的ZIP文件",false); } return $archive_files; } public static function setup_install($app){ $path = iPHP_APP_DIR.'/'.$app.'/iCMS.APP.INSTALL.php'; if(is_file($path)){ return self::setup_exec($path,$app,'安装'); } } public static function setup_exec($file,$name,$title='升级') { $func = require_once $file; if(is_callable($func)){ $msg = self::msg('执行['.$name.']'.$title.'程序',true); try { self::$test OR $msg .= $func(); $msg.= self::msg($title.'顺利完成!',true); $msg.= self::msg('删除'.$title.'程序!',true); } catch ( Exception $e ) { $msg.= self::msg('['.$name.']'.$title.'出错',false); } }else{ $msg= self::msg('['.$name.']'.$title.'出错',false); $msg.= self::msg('找不到'.$title.'程序',false); } iFS::del($file); return $msg; } public static function setup_func($func) { return $func; } public static function rootpath($d='APP'){ $d=='APP' && $dir = iPHP_APP_DIR; $d=='TPL' && $dir = iPHP_TPL_DIR; $ROOTPATH = self::$is_git?iPATH:$dir; return rtrim($ROOTPATH,DIRECTORY_SEPARATOR); } public static function check_must($store){ if(empty($store)){ iUI::alert('请求出错','js:1',10); } if(empty($store['code'])){ iUI::alert($store['msg'],'js:1',10); } } public static function msg($text,$s=0){ $text = iSecurity::filter_path($text); if(self::$msg_mode=='alert'){ $s OR iUI::alert($text); }else{ return str_pad($text,80,'.').iUI::check($s).'<br />'; } } public static function create_bakdir($a,&$msg){ $bakdir = iPATH.'.backup/'.$a.'_'.date("Ymd"); iFS::mkdir($bakdir) && $msg.= self::msg('备份目录创建完成',true); return $bakdir; } public static function extract_test($archive_files,$ROOTPATH,&$msg){ $continue = true; if($archive_files)foreach ($archive_files as $file) { $folder = $file['folder'] ? $file['filename'] : dirname($file['filename']); $dp = $ROOTPATH .'/'.trim($folder,'/').'/'; if (!iFS::checkdir($dp) && iFS::ex($dp)) { $continue = false; $msg .= self::msg($dp . '目录无写权限',false); } if (empty($file['folder'])) { $fp = $ROOTPATH .'/'. $file['filename']; if (file_exists($fp) && !@is_writable($fp)) { $continue = false; $msg.= self::msg($fp . '文件无写权限',false); } } } $msg = iSecurity::filter_path($msg); return array($msg,$continue); } public static function extract($archive_files,$ROOTPATH,$bakdir=null){ foreach ($archive_files as $file) { $folder = $file['folder'] ? $file['filename'] : dirname($file['filename']); $dp = $ROOTPATH .'/'.trim($folder,'/').'/'; if (!iFS::ex($dp)) { self::$test OR iFS::mkdir($dp); $msg.= self::msg('创建文件夹 [' . $dp . ']',true); } if (!$file['folder']) { $fp = $ROOTPATH .'/'. $file['filename']; if($bakdir){ $bfp = $bakdir . '/' . $file['filename']; iFS::backup($fp,$bfp) && $msg.= self::msg('备份 [' . $fp . '] 文件 到 [' . $bfp . ']',true); } self::$test OR iFS::write($fp, $file['content']); $msg.= self::msg('安装文件 [' . $fp . ']',true); } } $msg = iSecurity::filter_path($msg); return $msg; } public static function get($vars=0,$field='sid'){ if(empty($vars)) return array(); if($vars=='all'){ $sql = '1=1'; $is_multi = true; }else{ list($vars,$is_multi) = iSQL::multi_var($vars); $sql = iSQL::in($vars,$field,false,true); } $data = array(); $rs = iDB::all("SELECT * FROM `#iCMS@__apps_store` where {$sql}"); if($rs){ $_count = count($rs); for ($i=0; $i < $_count; $i++) { $data[$rs[$i][$field]]= $rs[$i]; } $is_multi OR $data = $data[$vars]; } if(empty($data)){ return; } return $data; } public static function get_array($vars,$field="*",$orderby=''){ $sql = iSQL::where($vars,false); $sql.= 'order by '.($orderby?$orderby:'id ASC'); $rs = iDB::all("SELECT {$field} FROM `#iCMS@__apps_store` where {$sql}"); $_count = count($rs); for ($i=0; $i < $_count; $i++) { $data[$rs[$i]['sid']] = $rs[$i]; } return $data; } public static function remote($url){ iHttp::$CURLOPT_TIMEOUT = 60; iHttp::$CURLOPT_CONNECTTIMEOUT = 10; iHttp::$CURLOPT_REFERER = $_SERVER['HTTP_REFERER']; iHttp::$CURLOPT_USERAGENT = $_SERVER['HTTP_USER_AGENT']; iHttp::$CURLOPT_HTTPHEADER = array('AUTHORIZATION: '.self::$authcode); $queryArray = array( 'iPHP_APP' => 'wxAppCMS', 'iCMS_VERSION' => iCMS_VERSION, 'iCMS_RELEASE' => iCMS_RELEASE, 'iCMS_HASH' => iCMS_HASH, 'GIT_COMMIT' => GIT_COMMIT, 'GIT_TIME' => GIT_TIME, 'iCMS_HOST' => $_SERVER['HTTP_HOST'], ); $url = iURL::make($queryArray,$url); $data = iHttp::remote($url); return $data; } public static function remote_update($store) { $url = self::STORE_URL.'/git/update?sid='.$store['sid'] ."&version=".$store['version'] .'&git_sha=' .$store['git_sha'] .'&git_time=' .$store['git_time'] .'&authkey='.$store['authkey'] .'&transaction_id='.$store['transaction_id']; self::$authcode = $store['data']; $json = self::remote($url); $array = json_decode($json,true); return $array; } public static function remote_send($sid,$do='get',$add=null){ $time = time(); $host = $_SERVER['HTTP_HOST']; $key = md5(iPHP_KEY.$host.$time); $query = compact(array('sid','key','host','time')); $add && $query = array_merge($query,$add); $url = self::STORE_URL.'/'.$do.'/'.$sid.'?'.http_build_query($query); $json = self::remote($url); $array = json_decode($json,true); return $array; } public static function remote_all($name='app'){ $data = array(); $url = self::STORE_URL.'/all/'.$name; isset($_GET['premium']) && $url.='?premium='.$_GET['premium']; $json = self::remote($url); $json && $data = json_decode($json,true); return $data; } public static function pay_notify(){ $query = array( 'authkey' => $_GET['authkey'], 'sid' => $_GET['sid'] ); $url = self::STORE_URL.'/payment/notify?'.http_build_query($query); echo self::remote($url); } public static function premium_dialog($sid,$array,$title){ iUI::$break = false; iUI::$dialog['quickClose'] = false; iUI::$dialog['modal'] = true; iUI::$dialog['ok'] = true; iUI::$dialog['cancel'] = true; iUI::$dialog['ok:js'] = 'window.parent.clear_pay_notify_timer();'; iUI::$dialog['cancel:js'] = 'window.parent.clear_pay_notify_timer();'; iUI::dialog($array['dialog_html'],'js:1',1000000); echo '<script type="text/javascript"> var j = '.json_encode(array($array['authkey'],$sid)).'; window.parent.pay_notify(j,d); </script>'; } public static function setup($url,$store,$local=null){ @set_time_limit(0); iUI::close_dialog(); $sid = 0; if(self::$is_update && $local){ $sid = $local['sid']; apps_store::$authcode = $local['data']; $query = array('sid'=>$local['sid'],'authkey'=>$local['authkey']); $store['premium'] && $query['transaction_id'] = $local['transaction_id']; $query['store_update'] = 1; }else{ apps_store::$authcode = $store['authcode']; $query = array('sid'=>$store['id'],'authkey'=>$store['authkey']); $store['premium'] && $query['transaction_id'] = $_GET['transaction_id']; } $zipname = md5($store['authkey'].$local['authcode']).'.zip'; $zipurl = apps_store::STORE_URL.$url.'?'.http_build_query($query); $msg = self::download($zipurl,$store['name'],$zipname); self::$success OR iUI::dialog($msg,'js:1',1000000); $data = array_merge($query,array( 'app' => $store['app'], 'name' => $store['name'], 'git_time' => $store['git_time'], 'git_sha' => $store['git_sha'], 'version' => $store['version'], 'type' => $store['type'], 'authkey' => $store['authkey'], 'data' => $store['authcode'] )); switch ($store['type']) { case '0': $msg.= self::install_app($store['app']); if(self::$success){ self::$app_id && $data['appid'] = self::$app_id; self::save($data,$sid); iUI::dialog( '<div style="overflow-y: auto;max-height: 500px;">'.$msg.'</div>', ( self::$is_update? 'js:1'://更新 'url:'.__ADMINCP__."=apps&do=add&id=".self::$app_id ),30 ); return true; } break; case '1': $msg.= self::install_template($store['app']); if(self::$success){ $data['appid'] = 0; self::save($data,$sid); iUI::dialog( '<div style="overflow-y: auto;max-height: 500px;">'.$msg.'</div>', 'js:1',1000000 ); return true; } break; } iUI::dialog('<div style="overflow-y: auto;max-height: 500px;">'.$msg.'</div>','js:1',1000000); } public static function del($id=null,$field='appid',$send=true){ if(isset($_GET['sid']) && $field!='sid'){ $id = (int)$_GET['sid']; $field = 'sid'; } iDB::query("DELETE FROM `#iCMS@__apps_store` WHERE `$field` = '$id'"); $send && self::remote_send($id,'del'); } public static function save($array,$sid=null){ $fields = array('sid', 'appid', 'app', 'name', 'version', 'authkey', 'git_sha', 'git_time', 'transaction_id', 'data', 'addtime', 'uptime', 'type', 'status' ); $data = compact($fields); $data = array_merge($data,$array); iSQL::filter_data($data,$fields); if(self::$is_update){ $data['uptime'] = time(); unset($data['appid'],$data['authkey'],$data['data']);//不更新 iDB::update('apps_store',$data,array('sid'=>$sid)); }else{ $data['addtime'] = time(); iDB::insert('apps_store',$data); } } }